package cn.ug.login.web.controller;

import cn.ug.account.bean.AccountBean;
import cn.ug.account.bean.AuthorizeBean;
import cn.ug.account.bean.PersonnelBean;
import cn.ug.account.bean.status.AccountStatus;
import cn.ug.analyse.bean.ChannelUserBean;
import cn.ug.bean.LoginBean;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.*;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.ChannelEnum;
import cn.ug.enums.RateKeyEnum;
import cn.ug.enums.ThirdSourceEnum;
import cn.ug.feign.*;
import cn.ug.login.service.LoginSessionService;
import cn.ug.login.service.VerificationCodeService;
import cn.ug.member.bean.response.MemberThirdFindBean;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.member.mq.MemberLabelMQ;
import cn.ug.member.mq.MemberPasswordStatusMQ;
import cn.ug.mq.DelayMessagePostProcessor;
import cn.ug.service.SystemService;
import cn.ug.util.UF;
import cn.ug.util.WxUtil;
import cn.ug.web.controller.BaseController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static cn.ug.config.QueueName.QUEUE_MEMBER_LABEL;
import static cn.ug.config.QueueName.QUEUE_MEMBER_PASSWORD_STATUS_DELAY;
import static cn.ug.login.bean.type.VerificationCodeType.FORGET_PASSWORD;
import static cn.ug.login.bean.type.VerificationCodeType.SHORTCUT_LOGIN;
import static cn.ug.util.RedisConstantUtil.CHANNEL_CASH_KEY;

/**
 * 系统账号相关服务
 *
 * @author kaiwotech
 */
@RestController
@RequestMapping("user")
public class LoginController extends BaseController {
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Resource
    private AccountService accountService;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private MemberAddressService memberAddressService;
    @Resource
    private PersonnelService personnelService;
    @Resource
    private LoginSessionService loginSessionService;
    @Resource
    private VerificationCodeService verificationCodeService;
    @Resource
    private AuthorizeService authorizeService;
    @Resource
    private SystemService systemService;
    @Resource
    private BankCardService bankCardService;
    @Resource
    private MemberThirdService memberThirdService;

    @Resource
    private ChannelService channelService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MemberOperationService memberOperationService;

    private String H5_DOMAIN = null;

    @Value("${spring.cloud.config.profile}")
    private String environMent;

    @Value("${web.domain.url-dev}")
    private String domainUrlDev;

    @Value("${web.domain.url-test}")
    private String domainUrlTest;

    @Value("${web.domain.url-deta}")
    private String domainUrlDeta;

    private static Logger logger = LoggerFactory.getLogger(LoginController.class);

    private static final String REGEX = "[a-zA-Z\\d+]{8,16}";


    /**
     * 登录
     *
     * @param loginName   用户名
     * @param password    密码
     * @param loginType   登录类型 1：系统维护账号 2：普通用户 3：会员
     * @param loginSource 登录来源 1：PC 2：Android App 3：IOS App
     * @param ip          IP地址
     * @param hostName    远程主机名
     * @return 是否登录成功
     */
    @RequestMapping("login")
    public SerializeObject login(String loginName, String password, Integer loginType, Integer loginSource, String ip, String hostName, String code, HttpServletRequest request) {
        info("登陆： loginName = [" + loginName + "], password = [" + password + "], loginType = [" + loginType + "], loginSource = [" + loginSource + "], ip = [" + ip + "], hostName = [" + hostName + "], cid = [" + request.getParameter("cid") + "]");
        if (null == loginType || StringUtils.isBlank(loginName) || StringUtils.isBlank(password)) {
            return new SerializeObjectError("00000002");
        }

        String cid = request.getParameter("cid");
        LoginBean loginBean = new LoginBean();
        loginBean.setAccessToken(UF.getRandomUUID());
        loginBean.setLoginType(loginType);
        loginBean.setLoginSource(loginSource);
        loginBean.setIp(ip);
        loginBean.setHostName(hostName);
        loginBean.setLoginTime(System.currentTimeMillis());
        loginBean.setOnlineType(OnlineType.ONLINE);

        LoginResult loginResult = LoginResult.FAIL;
        password = DigestUtils.md5Hex(password);
        switch (loginType) {

            case LoginType.ADMINISTRATOR: {
                if (StringUtils.isNotBlank(code)) {
                    if (!verificationCodeService.check(SHORTCUT_LOGIN, loginName, code)) {
                        return new SerializeObjectError("13000102");
                    }
                }
                loginResult = loginAccount(loginName, password, loginBean);
                if (loginResult == LoginResult.NONE) {
                    loginResult = loginPersonnel(loginName, password, loginBean);
                }
                break;
            }
            case LoginType.USER: {
                loginResult = loginPersonnel(loginName, password, loginBean);
                break;
            }
            case LoginType.MEMBER: {
                loginResult = loginMember(loginName, password, loginBean, request);
                break;

            }
            default:
        }

        switch (loginResult) {
            case SUCCESS: {
                if (StringUtils.isNotBlank(cid)) {
                    SerializeObject<MemberThirdFindBean> result = memberThirdService.find(null, loginBean.getId(), ThirdSourceEnum.PUSH.getType());
                    //当前会员号已经绑定其他cid  并且此cid和当前登陆的cid不一致  进行清除
                    if (result.getData() != null && !result.getData().getOpenId().equals(cid)) {
                        memberThirdService.delete(result.getData().getOpenId(), ThirdSourceEnum.PUSH.getType());
                    }


                    //第三方账号绑定
                    SerializeObject<MemberThirdFindBean> serializeObject = memberThirdService.find(cid, null, ThirdSourceEnum.PUSH.getType());
                    if (serializeObject.getData() == null) {
                        memberThirdService.save(cid, loginBean.getId(), ThirdSourceEnum.PUSH.getType(), loginSource);
                    } else {
                        //已绑定的会员号和当前登陆的会员号不一致  更新会员号
                        if (!serializeObject.getData().getMemberId().equals(loginBean.getId())) {
                            memberThirdService.update(cid, loginBean.getId(), ThirdSourceEnum.PUSH.getType(), loginSource);
                        }
                    }
                }
                //systemService.log(LogType.LOGIN, "操作成功");
                systemService.log(LogType.LOGIN, cid, "操作成功", loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObject<>(ResultType.NORMAL, "操作成功", loginBean.getAccessToken());
            }
            case FAIL: {
                //systemService.log(LogType.LOGIN, getMessage("13000001"));
                systemService.log(LogType.LOGIN, cid, getMessage("13000001"), loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000001");
            }
            case LOCKED: {
                //systemService.log(LogType.LOGIN, getMessage("13000002"));
                systemService.log(LogType.LOGIN, cid, getMessage("13000002"), loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000002");
            }
            case NONE: {
                //systemService.log(LogType.LOGIN, getMessage("13000003"));
                systemService.log(LogType.LOGIN, cid, getMessage("13000003"), loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                if (loginType == LoginType.MEMBER) {
                    return new SerializeObjectError<>("13000005");
                } else {
                    return new SerializeObjectError<>("13000003");
                }
            }
            case PASSWORD_LIMIT: {
                String msg = getMessage("13000003");
                if (loginType == LoginType.MEMBER) {
                    SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.LOGIN_PASSWORD.getKey());
                    if (paramBean != null && paramBean.getData() != null) {
                        JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                        int wrongTimes = json.getIntValue("wrongTimes");
                        int minutes = json.getIntValue("minutes");
                        SerializeObjectError result = new SerializeObjectError<>("13000105");
                        msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                }
                //systemService.log(LogType.LOGIN, msg);
                systemService.log(LogType.LOGIN, cid, msg, loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000005");
            }
            default: {
                //systemService.log(LogType.LOGIN, getMessage("13000003"));
                systemService.log(LogType.LOGIN, cid, getMessage("13000003"), loginType, loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000003");
            }
        }
    }

    /**
     * 快捷登陆
     *
     * @param loginSource
     * @param loginName
     * @param inviteCode
     * @param staffId
     * @param channelId
     * @param lotteryId
     * @param code        验证码
     * @param request
     * @return
     */
    @RequestMapping("/shortcut/login")
    public SerializeObject login(Integer loginSource, String loginName,
                                 @RequestParam(value = "inviteCode", required = false) String inviteCode,
                                 @RequestParam(value = "staffId", required = false) String staffId,
                                 @RequestParam(value = "channelId", required = false) String channelId,
                                 @RequestParam(value = "lotteryId", required = false) Integer lotteryId,
                                 @RequestParam(value = "code", required = false) String code,
                                 HttpServletRequest request) {
        info("快捷登陆： loginName = [" + loginName + "], loginSource = [" + loginSource + "], channelId = [" + channelId + "], inviteCode = [" + inviteCode + "], lotteryId = [" + lotteryId +
                "], code = [" + code);
        if (StringUtils.isNotBlank(code)) {
            if (!verificationCodeService.check(SHORTCUT_LOGIN, loginName, code)) {
                return new SerializeObjectError("13000102");
            }
        }
        if (StringUtils.isBlank(loginName)) {
            return new SerializeObjectError("00000002");
        }
        loginSource = loginSource == null ? 1 : loginSource;
        if (StringUtils.isBlank(channelId)) {
            switch (loginSource) {
                case 2:
                    channelId = ChannelEnum.ANDROID.getId();
                    break;
                case 3:
                    channelId = ChannelEnum.IOS.getId();
                    break;
                case 4:
                    channelId = ChannelEnum.WECHAT.getId();
                    break;
            }
        }
        LoginBean loginBean = new LoginBean();
        loginBean.setAccessToken(UF.getRandomUUID());
        loginBean.setLoginSource(loginSource);
        loginBean.setLoginTime(System.currentTimeMillis());
        loginBean.setOnlineType(OnlineType.ONLINE);
        LoginResult loginResult = LoginResult.FAIL;
        loginResult = loginMember(loginSource, loginName, inviteCode, channelId, staffId, loginBean, request, lotteryId);
        switch (loginResult) {
            case SUCCESS: {
                String openId = request.getParameter("openId");
                if (StringUtils.isNotBlank(openId)) {
                    SerializeObject<MemberThirdFindBean> serializeObject = memberThirdService.find(openId, loginBean.getId(), ThirdSourceEnum.WXACCOUNT.getType());
                    if (serializeObject.getData() == null) {
                        memberThirdService.save(openId, loginBean.getId(), ThirdSourceEnum.WXACCOUNT.getType(), loginSource);
                    }
                }

                String cid = request.getParameter("cid");
                if (StringUtils.isNotBlank(cid)) {
                    SerializeObject<MemberThirdFindBean> result = memberThirdService.find(null, loginBean.getId(), ThirdSourceEnum.PUSH.getType());
                    //当前会员号已经绑定其他cid  并且此cid和当前登陆的cid不一致  进行清除
                    if (result.getData() != null && !result.getData().getOpenId().equals(cid)) {
                        memberThirdService.delete(result.getData().getOpenId(), ThirdSourceEnum.PUSH.getType());
                    }

                    //第三方账号绑定
                    SerializeObject<MemberThirdFindBean> serializeObject = memberThirdService.find(cid, null, ThirdSourceEnum.PUSH.getType());
                    if (serializeObject.getData() == null) {
                        memberThirdService.save(cid, loginBean.getId(), ThirdSourceEnum.PUSH.getType(), loginSource);
                    } else {
                        //cid已绑定的会员号和当前登陆的会员号不一致  更新会员号
                        if (!serializeObject.getData().getMemberId().equals(loginBean.getId())) {
                            memberThirdService.update(cid, loginBean.getId(), ThirdSourceEnum.PUSH.getType(), loginSource);
                        }
                    }
                }
                //systemService.log(LogType.LOGIN, "操作成功");
                systemService.log(LogType.LOGIN, cid, "操作成功", loginBean.getLoginType(), loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObject<>(ResultType.NORMAL, "操作成功", loginBean.getAccessToken());
            }
            case LOCKED: {
                //systemService.log(LogType.LOGIN, getMessage("13000002"));
                systemService.log(LogType.LOGIN, "", getMessage("13000002"), loginBean.getLoginType(), loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000002");
            }
            case PASSWORD_LIMIT: {
                String msg = getMessage("13000003");
                SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.LOGIN_PASSWORD.getKey());
                if (paramBean != null && paramBean.getData() != null) {
                    JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                    int wrongTimes = json.getIntValue("wrongTimes");
                    int minutes = json.getIntValue("minutes");
                    SerializeObjectError result = new SerializeObjectError<>("13000105");
                    msg = String.format(result.getMsg(), wrongTimes, minutes);
                    result.setMsg(msg);
                    return result;
                }
                //systemService.log(LogType.LOGIN, msg);
                systemService.log(LogType.LOGIN, "", msg, loginBean.getLoginType(), loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000005");
            }
            default: {
                //systemService.log(LogType.LOGIN, getMessage("13000006"));
                systemService.log(LogType.LOGIN, "", getMessage("13000006"), loginBean.getLoginType(), loginBean.getId(), loginBean.getName(), loginBean.getLoginName());
                return new SerializeObjectError<>("13000006");
            }
        }
    }

    /**
     * 退出登录
     *
     * @param accessToken 登录成功后分配的Key
     * @return 是否操作成功
     */
    @RequestMapping("logout")
    public SerializeObject logout(String accessToken) {
        systemService.log(LogType.LOGOUT, getMessage("00000001"));
        loginSessionService.remove(accessToken);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 检测是否在线、是否登录超时
     *
     * @param accessToken 登录成功后分配的Key
     * @return 是否在线
     */
    @RequestMapping("online")
    public SerializeObject<LoginBean> online(String accessToken) {
        LoginBean loginBean = loginSessionService.get(accessToken);
        if (null == loginBean || StringUtils.isBlank(loginBean.getLoginName())) {
            return new SerializeObject<>(ResultType.UNLOGIN, "00000102");
        } else if (loginBean.getOnlineType() != OnlineType.ONLINE) {
            return new SerializeObject<>(ResultType.UNLOGIN, "13000004");
        }
        // 重新赋值，防止值被更改
        if (loginBean.getLoginType() == LoginType.ADMINISTRATOR) {
            SerializeObject obj = accountService.find(accessToken, loginBean.getId());
            if (null != obj && obj.getCode() == ResultType.NORMAL) {
                AccountBean accountBean = (AccountBean) obj.getData();
                loginBean.setLoginName(accountBean.getLoginName());
                loginBean.setName(accountBean.getName());
                loginBean.setMobile(accountBean.getMobile());
            }
        }
        if (loginBean.getLoginType() == LoginType.USER) {
            SerializeObject obj = personnelService.find(accessToken, loginBean.getId());
            if (null != obj && obj.getCode() == ResultType.NORMAL) {
                PersonnelBean personnelBean = (PersonnelBean) obj.getData();
                loginBean.setLoginName(personnelBean.getLoginName());
                loginBean.setName(personnelBean.getName());
                loginBean.setMobile(personnelBean.getMobile());
            }
        }
        if (loginBean.getLoginType() == LoginType.MEMBER) {
            SerializeObject obj = memberUserService.findById(loginBean.getId());
            if (null != obj && obj.getCode() == ResultType.NORMAL) {
                MemberUserBean memberUserBean = (MemberUserBean) obj.getData();
                loginBean.setLoginName(memberUserBean.getLoginName());
                loginBean.setName(memberUserBean.getName());
                loginBean.setHeadImage(memberUserBean.getHead());
                loginBean.setMobile(memberUserBean.getMobile());

                // 获取是否绑卡
                if (YesNo.NO.getValue().equals(loginBean.getBindCard())) {
                    SerializeObject serializeObject = bankCardService.validateBindBankCard(loginBean.getId());
                    if (null != serializeObject && serializeObject.getCode() == ResultType.NORMAL) {
                        loginBean.setBindCard(YesNo.YES.getValue());
                    }
                }

                // 是否设置交易密码
                if (YesNo.NO.getValue().equals(loginBean.getBindPayPassword())) {
                    if (StringUtils.isNotBlank(memberUserBean.getPayPassword())) {
                        loginBean.setBindPayPassword(YesNo.YES.getValue());
                    }
                }
                // 是否设置收货地址
                SerializeObject<Integer> numBean = memberAddressService.getAddressNum(loginBean.getId());
                if (numBean == null || numBean.getData() == null || numBean.getData() < 1) {
                    loginBean.setBindAddress(YesNo.NO.getValue());
                } else {
                    loginBean.setBindAddress(YesNo.YES.getValue());
                }

                /*// 是否设置收货地址
                if(YesNo.NO.getValue().equals(loginBean.getBindAddress())) {
                    SerializeObject serializeObject = memberAddressService.findByMemberId(loginBean.getId());
                    if(null != serializeObject && serializeObject.getCode() == ResultType.NORMAL && null != serializeObject.getData()) {
                        loginBean.setBindAddress(YesNo.YES.getValue());
                    }
                }*/
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, loginBean);
    }

    /**
     * 忘记密码
     *
     * @param loginType   登录类型 1：系统维护账号 2：普通用户 3：会员
     * @param loginSource 登录来源 1：PC 2：Android App 3：IOS App
     * @param loginName   用户名
     * @param code        验证码
     * @return 是否登录成功
     */
    @RequestMapping("forgetPassword")
    public SerializeObject forgetPassword(Integer loginType, Integer loginSource, String loginName, String password, String code) {
        if (null == loginType || StringUtils.isBlank(loginName) || StringUtils.isBlank(password) || StringUtils.isBlank(code)) {
            return new SerializeObjectError("00000002");
        }

        if (!verificationCodeService.check(FORGET_PASSWORD, loginName, code)) {
            return new SerializeObjectError("13000102");
        }

        switch (loginType) {
            case LoginType.ADMINISTRATOR: {
                /*SerializeObject<AccountBean> obj = accountService.loginName(loginName);
                if(null == obj || obj.getCode() != ResultType.NORMAL) {
                    return new SerializeObjectError("13000003");
                }
                AccountBean accountBean = obj.getData();
                return accountService.updatePassword(accessToken, accountBean.getId(), password, newPassword);*/
                break;
            }
            case LoginType.USER: {
                /*SerializeObject<PersonnelBean> obj = personnelService.loginName(loginName);
                PersonnelBean personnelBean = null;
                if(null == obj || obj.getCode() != ResultType.NORMAL) {
                    return new SerializeObjectError("13000003");
                }
                personnelBean = obj.getData();
                return personnelService.updatePassword(accessToken, personnelBean.getId(), password, newPassword);*/
                break;
            }
            case LoginType.MEMBER: {
                SerializeObject<MemberUserBean> obj = memberUserService.findByLoginName(loginName);
                MemberUserBean memberUserBean = null;
                if (null == obj || obj.getCode() != ResultType.NORMAL) {
                    return new SerializeObjectError("13000003");
                }
                memberUserBean = obj.getData();
                return memberUserService.forgetPassword(memberUserBean.getId(), password);
            }
            default:
        }
        return new SerializeObjectError<>("00000005");
    }

    /**
     * 修改当前登录账号密码
     *
     * @param accessToken 登录成功后分配的Key
     * @param password    原密码
     * @param newPassword 新密码
     * @return 是否登录成功
     */
    @RequestMapping("updatePassword")
    public SerializeObject updatePassword(@RequestHeader("accessToken") String accessToken, String password, String newPassword) {
        if (StringUtils.isBlank(password) || StringUtils.isBlank(newPassword)) {
            return new SerializeObjectError("00000002");
        }

        LoginBean loginBean = LoginHelper.getLoginBean();
        if (null == loginBean) {
            return new SerializeObjectError("00000102");
        }

        switch (loginBean.getLoginType()) {
            case LoginType.ADMINISTRATOR: {
                return accountService.updatePassword(accessToken, password, newPassword);
            }
            case LoginType.USER: {
                return personnelService.updatePassword(accessToken, password, newPassword);
            }
            case LoginType.MEMBER: {
                return memberUserService.updatePassword(accessToken, password, newPassword);
            }
            default:
        }
        return new SerializeObjectError<>("00000005");
    }

    /**
     * 注册
     *
     * @param loginSource 登录来源 1：PC 2：Android App 3：IOS App, 4:微信（H5）
     * @param loginName   用户名
     * @param staffId     新的渠道成员id
     * @param lotteryId   抽奖活动id
     * @return 是否登录成功
     */
    @RequestMapping("register")
    public SerializeObject register(Integer loginSource, String loginName, String password,
                                    @RequestParam(value = "inviteCode", required = false) String inviteCode,
                                    @RequestParam(value = "channelId", required = false) String channelId,
                                    @RequestParam(value = "staffId", required = false) String staffId,
                                    @RequestParam(value = "lotteryId", required = false) Integer lotteryId) {
        info("注册：loginName = [" + loginName + "],loginSource = [" + loginSource + "], channelId = [" + channelId + "], inviteCode = [" + inviteCode + "], lotteryId = [" + lotteryId + "], staffId = [" + staffId + "]");
        if (null == loginSource || loginSource <= 0 || StringUtils.isBlank(loginName) || StringUtils.isBlank(password)) {
            return new SerializeObjectError("00000002");
        }
        loginSource = loginSource == null ? 1 : loginSource;
        if (StringUtils.isBlank(channelId)) {
            switch (loginSource) {
                case 2:
                    channelId = ChannelEnum.ANDROID.getId();
                    break;
                case 3:
                    channelId = ChannelEnum.IOS.getId();
                    break;
                case 4:
                    channelId = ChannelEnum.WECHAT.getId();
                    break;
            }
        }
        return memberUserService.register(loginSource, loginName, password, inviteCode, channelId, staffId, lotteryId);
        /*if(null != obj && obj.getCode() == ResultType.NORMAL) {
            return new SerializeObject<>(ResultType.NORMAL, "13000101");
        }
        return new SerializeObjectError("13000100");*/
    }

    /**
     * 微信接入
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @RequestMapping("wx/joinUp")
    public void joinUp(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");

        PrintWriter out = resp.getWriter();
        if (WxUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }
    }

    /**
     * 获取微信授权地址
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "getWxAccreditUrl", method = RequestMethod.GET)
    public void accredit(HttpServletRequest request,
                         HttpServletResponse response) throws IOException {
        if (environMent.equalsIgnoreCase("dev"))
            H5_DOMAIN = domainUrlDev;

        if (environMent.equalsIgnoreCase("test"))
            H5_DOMAIN = domainUrlTest;

        if (environMent.equalsIgnoreCase("beta"))
            H5_DOMAIN = domainUrlDeta;

        /**授权回调地址**/
        String wxAccreditCallBackUrl = H5_DOMAIN + "/login.html";
        logger.info("微信回调地址url:" + wxAccreditCallBackUrl);
        String accreditUrl = WxUtil.getAccreditUrl(wxAccreditCallBackUrl);
        response.sendRedirect(accreditUrl);
    }


    /**
     * web端调用传人code 做账号绑定校验
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/callback")
    public SerializeObject callback(HttpServletRequest request,
                                    HttpServletResponse response) {
        String code = request.getParameter("code");
        if (StringUtils.isBlank(code)) {
            return new SerializeObjectError("00000002");
        }
        JSONObject jsonObject = WxUtil.getAccreditAccesstokenByCode(code);
        String openId = jsonObject.getString("openid");

        /**通过openId查询用户绑定的信息 没有绑定就提交前端要求登陆**/
        if (StringUtils.isNotBlank(openId)) {
            SerializeObject<MemberThirdFindBean> serializeObject = memberThirdService.find(openId, null, ThirdSourceEnum.WXACCOUNT.getType());
            HashMap resultMap = new HashMap();
            resultMap.put("openId", openId);
            //未查询到数据  即：尚未绑定
            if (serializeObject.getData() == null) {
                return new SerializeObject<>(ResultType.ERROR, "尚未绑定账号", resultMap);
            }
            String memberId = serializeObject.getData().getMemberId();
            SerializeObject<MemberUserBean> userBean = memberUserService.findById(memberId);
            if (userBean.getData() == null) {
                return new SerializeObject<>(ResultType.ERROR, userBean.getMsg(), resultMap);
            }
            //已绑定
            LoginBean loginBean = new LoginBean();
            loginBean.setAccessToken(UF.getRandomUUID());
            loginBean.setLoginSource(4);//微信
            loginBean.setLoginTime(System.currentTimeMillis());
            loginBean.setOnlineType(OnlineType.ONLINE);
            LoginResult loginResult = LoginResult.FAIL;
            loginResult = loginMember(4, userBean.getData().getLoginName(),
                    ChannelEnum.WECHAT.getId(), "", null, loginBean, request, null);

            switch (loginResult) {
                case SUCCESS: {
                    systemService.log(LogType.LOGIN, "操作成功");
                    resultMap.put("accessToken", loginBean.getAccessToken());
                    return new SerializeObject<>(ResultType.NORMAL, "操作成功", resultMap);
                }
                case LOCKED: {
                    systemService.log(LogType.LOGIN, getMessage("13000002"));
                    return new SerializeObjectError<>("13000002");
                }
                default: {
                    systemService.log(LogType.LOGIN, getMessage("13000006"));
                    return new SerializeObjectError<>("13000006");
                }
            }

        }
        return new SerializeObject();
    }


    /**
     * 渠道登陆信息
     *
     * @param loginName 登陆用户名
     * @param password  登陆密码
     * @param type      类型 0渠道商户  1渠道成员
     */
    @RequestMapping(value = "channel/login", method = RequestMethod.POST)
    public SerializeObject channelLogin(String loginName, String password, Integer type, HttpServletRequest request) {
        if (StringUtils.isBlank(loginName)) {
            return new SerializeObjectError("13000107");
        }


        if (StringUtils.isBlank(password) || !password.matches(REGEX))
            return new SerializeObjectError<>("13000106");

        SerializeObject<ChannelUserBean> serializeObject = channelService.verifyLogin(loginName, password, type);
        if (serializeObject != null && serializeObject.getData() != null) {
            String accessToken = UF.getRandomUUID();
            String key = CHANNEL_CASH_KEY + loginName;
            String accessTokenInfo = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(accessTokenInfo)) {
                redisTemplate.delete(key);
                redisTemplate.delete(accessTokenInfo);
            }
            ChannelUserBean channelUserBean = serializeObject.getData();
            channelUserBean.setAccessToken(accessToken);
            redisTemplate.opsForValue().set(accessToken, JSONObject.toJSON(channelUserBean).toString());
            redisTemplate.opsForValue().set(key, accessToken);
            return new SerializeObject<>(ResultType.NORMAL, "操作成功", channelUserBean);
        }
        return serializeObject;
    }

    /**
     * 修改登陆密码
     *
     * @param id             商户或者渠道成员id
     * @param password       登陆密码
     * @param affirmPassword 确认登陆密码
     * @param type           类型 0渠道商户  1渠道成员
     */
    @RequestMapping(value = "channel/updatePassword", method = RequestMethod.POST)
    public SerializeObject updatePassword(@RequestHeader("accessToken") String accessToken, Long id, String password, String affirmPassword, Integer type, HttpServletRequest request) {
        ChannelUserBean channelUserBean = loginSessionService.getchannelUserInfo(accessToken);
        if (channelUserBean == null)
            return new SerializeObjectError("00000102");

        if (StringUtils.isBlank(password) || StringUtils.isBlank(affirmPassword) || !password.matches(REGEX))
            return new SerializeObjectError<>("13000106");

        if (id == null || type == null) {
            return new SerializeObjectError("00000002");
        }

        if (!password.equals(affirmPassword))
            return new SerializeObjectError<>("13000105");


        SerializeObject serializeObject = channelService.updatePassword(id, password, type, null);
        if (serializeObject != null && serializeObject.getCode() == 200) {
            channelUserBean.setPassWrodStatus(1);
            redisTemplate.opsForValue().set(accessToken, JSONObject.toJSON(channelUserBean).toString());
        }

        return serializeObject;
    }

    /**
     * 忘记密码
     *
     * @param mobile
     * @param password
     * @param request
     * @return
     */
    @RequestMapping(value = "channel/forgetPassword", method = RequestMethod.POST)
    public SerializeObject forgetPassword(String mobile, String password, HttpServletRequest request) {
        if (StringUtils.isBlank(mobile))
            return new SerializeObjectError("00000002");

        if (StringUtils.isBlank(password) || !password.matches(REGEX))
            return new SerializeObjectError<>("13000106");

        SerializeObject serializeObject = channelService.updatePassword(null, password, 1, mobile);
        return serializeObject;
    }

    @RequestMapping(value = "channel/online", method = RequestMethod.GET)
    public SerializeObject<ChannelUserBean> channelOnline(String accessToken) {
        ChannelUserBean channelUserBean = loginSessionService.getchannelUserInfo(accessToken);
        if (channelUserBean == null)
            return new SerializeObjectError("00000102");

        return new SerializeObject<>(ResultType.NORMAL, "操作成功", channelUserBean);
    }

    @RequestMapping(value = "channel/logout", method = RequestMethod.GET)
    public SerializeObject channelLogout(String accessToken) {
        ChannelUserBean channelUserBean = loginSessionService.getchannelUserInfo(accessToken);
        if (channelUserBean == null)
            return new SerializeObjectError("00000102");

        redisTemplate.delete(accessToken);
        return new SerializeObject<>(ResultType.NORMAL, "操作成功");
    }

    /**
     * 管理员账号登录
     *
     * @param loginName 登录名
     * @param password  密码
     * @param loginBean 登录信息
     * @return 1：登录成功 2：账号不存在 3：账号已禁用 4：账号或密码不正确
     */
    private LoginResult loginAccount(String loginName, String password, LoginBean loginBean) {
        SerializeObject<AccountBean> obj = accountService.loginName(loginName);
        AccountBean accountBean = null;
        if (null != obj && obj.getCode() == ResultType.NORMAL) {
            accountBean = obj.getData();
        }
        if (null == accountBean || StringUtils.isBlank(accountBean.getId())) {
            return LoginResult.NONE;
        }
        if (!password.equalsIgnoreCase(accountBean.getPassword())) {
            return LoginResult.FAIL;
        }
        if (accountBean.getStatus() == AccountStatus.LOCK) {
            return LoginResult.LOCKED;
        }

        loginBean.setLoginType(LoginType.ADMINISTRATOR);
        loginBean.setId(accountBean.getId());
        loginBean.setLoginName(loginName);
        loginBean.setName(accountBean.getName());
        loginBean.setMobile(accountBean.getMobile());

        // 获取权限
        SerializeObject<List<AuthorizeBean>> o = authorizeService.findAllListWithPid();
        if (null != o && o.getCode() == ResultType.NORMAL) {
            Set<String> authorizeSet = new HashSet<>();
            List<AuthorizeBean> authorizeBeanList = o.getData();
            for (AuthorizeBean authorizeBean : authorizeBeanList) {
                authorizeSet.add(authorizeBean.getActionValue());
            }
            loginBean.setAuthorizeSet(authorizeSet);
        }

        loginSessionService.put(loginBean.getAccessToken(), loginBean);
        return LoginResult.SUCCESS;
    }

    /**
     * 普通账号登录
     *
     * @param loginName 登录名
     * @param password  密码
     * @param loginBean 登录信息
     * @return 1：登录成功 2：账号不存在 3：账号已禁用 4：账号或密码不正确
     */
    private LoginResult loginPersonnel(String loginName, String password, LoginBean loginBean) {
        SerializeObject<PersonnelBean> obj = personnelService.loginName(loginName);
        PersonnelBean personnelBean = null;
        if (null != obj && obj.getCode() == ResultType.NORMAL) {
            personnelBean = obj.getData();
        }
        if (null == personnelBean || StringUtils.isBlank(personnelBean.getId())) {
            return LoginResult.NONE;
        }
        if (!password.equalsIgnoreCase(personnelBean.getPassword())) {
            return LoginResult.FAIL;
        }
        if (personnelBean.getStatus() == AccountStatus.LOCK) {
            return LoginResult.LOCKED;
        }

        loginBean.setLoginType(LoginType.USER);
        loginBean.setId(personnelBean.getId());
        loginBean.setLoginName(loginName);
        loginBean.setName(personnelBean.getName());
        loginBean.setMobile(personnelBean.getMobile());

        // 获取权限
        SerializeObject<List<AuthorizeBean>> o = authorizeService.findListByPersonnel(personnelBean.getId());
        if (null != o && o.getCode() == ResultType.NORMAL) {
            Set<String> authorizeSet = new HashSet<>();
            List<AuthorizeBean> authorizeBeanList = o.getData();
            for (AuthorizeBean authorizeBean : authorizeBeanList) {
                authorizeSet.add(authorizeBean.getActionValue());
            }
            loginBean.setAuthorizeSet(authorizeSet);
        }

        loginSessionService.put(loginBean.getAccessToken(), loginBean);
        return LoginResult.SUCCESS;
    }

    /**
     * 会员账号登录
     *
     * @param loginName 登录名
     * @param password  密码
     * @param loginBean 登录信息
     * @return 1：登录成功 2：账号不存在 3：账号已禁用 4：账号或密码不正确
     */
    private LoginResult loginMember(String loginName, String password, LoginBean loginBean, HttpServletRequest request) {
        SerializeObject<MemberUserBean> obj = memberUserService.findByLoginName(loginName);
        MemberUserBean memberUserBean = null;
        if (null != obj && obj.getCode() == ResultType.NORMAL) {
            memberUserBean = obj.getData();
        }
        if (null == memberUserBean || StringUtils.isBlank(memberUserBean.getId())) {
            return LoginResult.NONE;
        }
        int isLimited = 0;
        int wrongTimes = 0;
        int minutes = 0;
        SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.LOGIN_PASSWORD.getKey());
        log.info("登陆限制参数：" + JSON.toJSONString(paramBean));
        log.info("会员信息：" + JSON.toJSONString(memberUserBean));
        if (paramBean != null && paramBean.getData() != null) {
            JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
            isLimited = json.getIntValue("isLimited");
            wrongTimes = json.getIntValue("wrongTimes");
            minutes = json.getIntValue("minutes");
            if (isLimited == 1 && memberUserBean.getPasswordStatus() == 1) {
                return LoginResult.PASSWORD_LIMIT;
            }
        }
        if (!password.equalsIgnoreCase(memberUserBean.getPassword())) {
            if (isLimited == 1) {
                int actualWrongTimes = memberUserBean.getPasswordWrongTimes();
                actualWrongTimes++;
                int status = 0;
                if (wrongTimes <= actualWrongTimes) {
                    status = 1;
                }
                memberUserService.modifyWrongTimes(memberUserBean.getId(), 1, actualWrongTimes, status);
                if (wrongTimes <= actualWrongTimes) {
                    MemberPasswordStatusMQ mq = new MemberPasswordStatusMQ();
                    mq.setMemberId(memberUserBean.getId());
                    mq.setType(1);
                    amqpTemplate.convertAndSend(QUEUE_MEMBER_PASSWORD_STATUS_DELAY, mq, new DelayMessagePostProcessor(minutes * 60 * 1000));
                    return LoginResult.PASSWORD_LIMIT;
                }
            }
            return LoginResult.FAIL;
        }
        if (memberUserBean.getStatus() == AccountStatus.LOCK) {
            return LoginResult.LOCKED;
        }

        memberUserService.modifyWrongTimes(memberUserBean.getId(), 1, 0, 0);
        //保存登录信息--等于来源
        memberUserService.updateLoginSource(memberUserBean.getId(), loginBean.getLoginSource());

        loginBean.setInviteCode(memberUserBean.getInviteCode());
        loginBean.setLoginType(LoginType.MEMBER);
        loginBean.setId(memberUserBean.getId());
        loginBean.setLoginName(loginName);
        loginBean.setName(memberUserBean.getName());
        loginBean.setMobile(memberUserBean.getMobile());
        loginBean.setHeadImage(memberUserBean.getHead());

        // 获取是否绑卡
        SerializeObject serializeObject = bankCardService.validateBindBankCard(loginBean.getId());
        if (null == serializeObject || serializeObject.getCode() != ResultType.NORMAL) {
            loginBean.setBindCard(YesNo.NO.getValue());
        } else {
            loginBean.setBindCard(YesNo.YES.getValue());
        }

        // 是否设置交易密码
        if (StringUtils.isBlank(memberUserBean.getPayPassword())) {
            loginBean.setBindPayPassword(YesNo.NO.getValue());
        } else {
            loginBean.setBindPayPassword(YesNo.YES.getValue());
        }
        // 是否设置收货地址
        SerializeObject<Integer> numBean = memberAddressService.getAddressNum(loginBean.getId());
        if (numBean == null || numBean.getData() == null || numBean.getData() < 1) {
            loginBean.setBindAddress(YesNo.NO.getValue());
        } else {
            loginBean.setBindAddress(YesNo.YES.getValue());
        }
        /*// 是否设置收货地址
        serializeObject = memberAddressService.findByMemberId(loginBean.getId());
        if(null == serializeObject || serializeObject.getCode() != ResultType.NORMAL || null == serializeObject.getData()) {
            loginBean.setBindAddress(YesNo.NO.getValue());
        } else {
            loginBean.setBindAddress(YesNo.YES.getValue());
        }*/

        MemberLabelMQ mq = new MemberLabelMQ();
        mq.setType(2);
        mq.setMemberId(memberUserBean.getId());
        mq.setMobile(memberUserBean.getMobile());
        mq.setIp(getIpAdrress(request));
        amqpTemplate.convertAndSend(QUEUE_MEMBER_LABEL, mq);

        loginSessionService.put(loginBean.getAccessToken(), loginBean);
        //登陆次数添加
        if (loginBean.getLoginSource() == 2 || loginBean.getLoginSource() == 3) {
            memberOperationService.loginAddClick(memberUserBean.getId());
        }
        return LoginResult.SUCCESS;
    }


    private LoginResult loginMember(int loginSource, String loginName, String inviteCode, String channelId, String staffId, LoginBean loginBean, HttpServletRequest request, Integer lotteryId) {
        SerializeObject<MemberUserBean> obj = memberUserService.findByLoginName(loginName);
        MemberUserBean memberUserBean = null;
        if (null != obj && obj.getCode() == ResultType.NORMAL) {
            memberUserBean = obj.getData();
        }
        if (null == memberUserBean || StringUtils.isBlank(memberUserBean.getId())) {
            SerializeObject registerBean = memberUserService.shortcutRegister(loginSource, loginName, inviteCode, channelId, staffId, lotteryId);
            if (null == obj || obj.getCode() != ResultType.NORMAL) {
                return LoginResult.FAIL;
            }
            SerializeObject<MemberUserBean> userBean = memberUserService.findByLoginName(loginName);
            if (null != userBean && userBean.getCode() == ResultType.NORMAL) {
                memberUserBean = userBean.getData();
                loginBean.setLoginType(LoginType.MEMBER);
                loginBean.setLoginName(loginName);
                if (memberUserBean != null) {
                    loginBean.setInviteCode(memberUserBean.getInviteCode());
                    loginBean.setId(memberUserBean.getId());
                    loginBean.setName(memberUserBean.getName());
                    loginBean.setMobile(memberUserBean.getMobile());
                    loginBean.setHeadImage(memberUserBean.getHead());
                }
            }
            loginBean.setBindPayPassword(YesNo.NO.getValue());
        } else {
            if (memberUserBean.getStatus() == AccountStatus.LOCK) {
                return LoginResult.LOCKED;
            }
            SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.LOGIN_PASSWORD.getKey());
            if (paramBean != null && paramBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                int isLimited = json.getIntValue("isLimited");
                if (isLimited == 1 && memberUserBean.getPasswordStatus() == 1) {
                    return LoginResult.PASSWORD_LIMIT;
                }
            }
            memberUserService.modifyWrongTimes(memberUserBean.getId(), 1, 0, 0);
            //保存登录信息--等于来源
            memberUserService.updateLoginSource(memberUserBean.getId(), loginBean.getLoginSource());

            loginBean.setInviteCode(memberUserBean.getInviteCode());
            loginBean.setLoginType(LoginType.MEMBER);
            loginBean.setId(memberUserBean.getId());
            loginBean.setLoginName(loginName);
            loginBean.setName(memberUserBean.getName());
            loginBean.setMobile(memberUserBean.getMobile());
            loginBean.setHeadImage(memberUserBean.getHead());
            // 是否设置交易密码
            if (StringUtils.isBlank(memberUserBean.getPayPassword())) {
                loginBean.setBindPayPassword(YesNo.NO.getValue());
            } else {
                loginBean.setBindPayPassword(YesNo.YES.getValue());
            }
        }


        // 获取是否绑卡
        SerializeObject serializeObject = bankCardService.validateBindBankCard(loginBean.getId());
        if (null == serializeObject || serializeObject.getCode() != ResultType.NORMAL) {
            loginBean.setBindCard(YesNo.NO.getValue());
        } else {
            loginBean.setBindCard(YesNo.YES.getValue());
        }
        // 是否设置收货地址
        SerializeObject<Integer> numBean = memberAddressService.getAddressNum(loginBean.getId());
        if (numBean == null || numBean.getData() == null || numBean.getData() < 1) {
            loginBean.setBindAddress(YesNo.NO.getValue());
        } else {
            loginBean.setBindAddress(YesNo.YES.getValue());
        }


        /*// 是否设置收货地址
        serializeObject = memberAddressService.findByMemberId(loginBean.getId());
        if(null == serializeObject || serializeObject.getCode() != ResultType.NORMAL || null == serializeObject.getData()) {
            loginBean.setBindAddress(YesNo.NO.getValue());
        } else {
            loginBean.setBindAddress(YesNo.YES.getValue());
        }*/
        if (memberUserBean != null) {
            MemberLabelMQ mq = new MemberLabelMQ();
            mq.setType(2);
            mq.setMemberId(memberUserBean.getId());
            mq.setMobile(memberUserBean.getMobile());
            mq.setIp(getIpAdrress(request));
            amqpTemplate.convertAndSend(QUEUE_MEMBER_LABEL, mq);
            loginSessionService.put(loginBean.getAccessToken(), loginBean);
        }

        //登陆次数添加
        if (loginSource == 2 || loginSource == 3) {
            memberOperationService.loginAddClick(memberUserBean.getId());
        }
        return LoginResult.SUCCESS;
    }

}
